library(sf)
library(leaflet)
library(rgdal)
library(RColorBrewer)
library(knitr)
library(kableExtra) # nice tables
library(fasterize) # -->Raster
library(raster)  # ACHTUNG raster() masked von "raster"
library(DT) # also nice tables (interactive sorting)
library(RCurl) # upload to ftp
library(tidyverse) # ACHTUNG raster() masked von "raster"

# Historsichwer vergleich: https://www.stadt-zuerich.ch/content/prd/de/index/statistik/publikationen-angebote/publikationen/webartikel/2018-01-30_Zuerich-waechst-in-die-Breite-und-in-die-Hoehe.html

options(encoding = "UTF-8")

url_wd = "D:/Tamedia/GSync/Datenteam/Projekte/202008_Zurich3D"

setwd(url_wd)
print(getwd())

1 Übersicht

Analyse der Entwicklung der Gebäudehöhen in der Stadt Zürich zwischen 2012 und jetzt (August 2020).

2 Daten

2.1 Quartierdefinitionen

Von Zürich Open Data

## Read Quartiergrenzen from Shapefile
grenzen <- st_read("Data_input/Quartiergrenzen/data/stzh.adm_statistische_quartiere_map_polygon.shp")
plot(grenzen$geometry, main = "Statistische Quartiere")  

knitr::kable(grenzen, digits = 0) %>%
  kable_styling(bootstrap_options = "striped", full_width = F, fixed_thead = T) %>% 
  scroll_box(height = "200px", fixed_thead = TRUE)

# datatable(st_drop_geometry(grenzen), class = 'cell-border stripe')

2.2 Gebäudedata

Daten von Zürich Open Data. Shapefiles mit den Grundrissen aller Gebäude. Die Höhe der Gebäude ist als Attribut hinterlegt (2.5 D)

aktueller Stand: https://data.stadt-zuerich.ch/dataset/geo_3d_blockmodell_lod1

Stand 2012: https://data.stadt-zuerich.ch/dataset/geo_3d_blockmodell_lod1_jahresendstand_2012

Detailiertere Metadatenbeschreibung: https://www.stadt-zuerich.ch/content/dam/stzh/ted/Deutsch/geoz/Geodaten_und_Plaene/Formulare_und_%20Merkblaetter/Technische_Datenbeschreibung_3D_Produkte.pdf

„Quelle: Stadt Zürich“

Es sind sowohl real existierende Gebäude erfasst, als auch eingereichte oder freigegebene Baubewilligungen. Für den Stand 2012 werden nur die real existierenden Gebäude und bewilligten Baubewilligungen berücksichtigt. Für den aktuellen Stand werden auch die eingereichten, aber noch nicht freigegebenen Baubewilligungen berücksichtigt.

Eingelesen werden die aufbereiteten Daten, bei denen bereits der Kreis und das Quartier für alle Gebäude hinterlegt wurden:

## read data ####
## Und korrigiere sofort alle Höhen um 3 Meter nach unter, weil diese von 3 Metern im Boden aus gemessen werden

shp_2_5_2012_all <- st_read("Data_output/2012_buildings.geojson", stringsAsFactors = FALSE, as_tibble=TRUE) %>%
  mutate(h_boden = h_boden + 3) %>%
  mutate(h_rel_trau = h_rel_trau - 3) %>%
  mutate(h_rel_firs = h_rel_firs - 3) %>%
  mutate(h_rel_mean = h_rel_mean - 3)
## Reading layer `2012_buildings' from data source `D:\Tamedia\GSync\Datenteam\Projekte\202008_Zurich3D\Data_output\2012_buildings.geojson' using driver `GeoJSON'
## Simple feature collection with 53222 features and 23 fields
## geometry type:  POLYGON
## dimension:      XY
## bbox:           xmin: 2677118 ymin: 1241839 xmax: 2689381 ymax: 1254150
## projected CRS:  CH1903+ / LV95
shp_2_5_aktuell_all <- st_read("Data_output/aktuell_buildings.geojson", stringsAsFactors = FALSE, as_tibble=TRUE) %>%
  mutate(h_boden = h_boden + 3) %>%
  mutate(h_rel_trau = h_rel_trau - 3) %>%
  mutate(h_rel_firs = h_rel_firs - 3) %>%
  mutate(h_rel_mean = h_rel_mean - 3)
## Reading layer `Aktuell_buildings' from data source `D:\Tamedia\GSync\Datenteam\Projekte\202008_Zurich3D\Data_output\Aktuell_buildings.geojson' using driver `GeoJSON'
## Simple feature collection with 59172 features and 23 fields
## geometry type:  POLYGON
## dimension:      XY
## bbox:           xmin: 2677118 ymin: 1241839 xmax: 2689381 ymax: 1254149
## projected CRS:  CH1903+ / LV95

Ausschnitt Daten:

knitr::kable(shp_2_5_aktuell_all[1:5, ], caption =  "", digits = 0) %>%
  kable_styling(bootstrap_options = "striped", full_width = F, fixed_thead = T) %>%
  scroll_box(width = "1080", height = "250px", fixed_thead = TRUE)
adat art ausr bem dach edat egid filt gid_3d h_boden h_trauf h_first h_mean h_rel_trau h_rel_firs h_rel_mean ogid otype qumess sta wichtig Kreis Quartier geometry
20140925 0 BATCHUSER OKMESS 6000 20090101 2372735 08 z41ac39cc00001a74-00-0001 409 416 416 416 8 8 8 z41ac39cc00001a74 BB NA real NA Kreis 1 Lindenhof POLYGON ((2683300 1247729, …
20140925 0 BATCHUSER OK NA 20090101 140856 08 z41ac39cc00001bb0-00-0001 408 421 428 425 14 21 17 z41ac39cc00001bb0 BB NA real NA Kreis 1 Lindenhof POLYGON ((2683327 1247163, …
20140925 1 BATCHUSER OK NA 20090101 140848 08 z41ac39cc00001bb3-00-0001 408 421 425 423 13 17 15 z41ac39cc00001bb3 BB NA real NA Kreis 1 Lindenhof POLYGON ((2683316 1247196, …
20190730 1 BATCHUSER OK NA 20090101 140766 08 z41ac39cc00001b48-00-0001 411 418 418 418 7 7 7 z41ac39cc00001b48 BB NA real NA Kreis 1 Lindenhof POLYGON ((2683129 1247439, …
20140925 0 BATCHUSER OK NA 20090101 2372673 08 z41ac39cc00001b49-00-0001 409 429 435 432 20 25 23 z41ac39cc00001b49 BB NA real NA Kreis 1 City POLYGON ((2682898 1247206, …

Status der Gebäude:
* Baubewilligung eingereicht
* Baubewilligung freigegeben
* Gebäude erstellt * Gebäude real existierend

print("2012:")
table(shp_2_5_2012_all$sta)

print("Aktuell:")
table(shp_2_5_aktuell_all$sta)
## [1] "2012:"
## 
## eingereicht    erstellt freigegeben        real 
##        1186         134         447       51455 
## [1] "Aktuell:"
## 
## eingereicht    erstellt freigegeben        real 
##        1461         356         449       56906

Grundfläche und Volumen pro Gebäude werden berechnet.

## calculate average height per quarter ####

# add area per building
shp_2_5_2012_all <- shp_2_5_2012_all %>%  mutate(area = as.numeric(st_area(shp_2_5_2012_all)))
shp_2_5_aktuell_all <- shp_2_5_aktuell_all %>%  mutate(area = as.numeric(st_area(shp_2_5_aktuell_all)))


# add volume per building FIRSTHöHE
shp_2_5_2012_all <- shp_2_5_2012_all %>%  mutate(volume_firs = area * h_rel_firs)
shp_2_5_aktuell_all <- shp_2_5_aktuell_all %>%  mutate(volume_firs = area * h_rel_firs)

# add volume per building TRAUFFHöHE
shp_2_5_2012_all <- shp_2_5_2012_all %>%  mutate(volume_trauf = area * h_rel_trau)
shp_2_5_aktuell_all <- shp_2_5_aktuell_all %>%  mutate(volume_trauf = area * h_rel_trau)

2.3 Daten Einschränkung

Es werden nur eigentliche Gebäude (Typ BB, Bodenbedeckung) berücksichtigt. Sogenannte “Einzelobjekte” (EO) werden nicht berücksichtigt (dies sind z.b. Brücken, Auffahrten zu Parkhäusern, aber auch die Bahnhofshalle)

Folgende Gebäudetypen werden unterschieden:
BB00: Gebaeude_Verwaltung
BB01: Gebaeude_Wohngebaeude
BB02: Gebaeude_Land_Forstwirtschaft
BB03: Gebaeude_Verkehr
BB04: Gebaeude_Handel
BB05: Gebaeude_Industrie_Gewerbe
BB06: Gebaeude_Gastgewerbe
BB07: Gebaeude_Nebengebaeude
EO08: Bruecke_Passerelle
EO12: Pfeiler
EO13: Unterstand
EO14: Silo_Turm_Gasometer
EO16: Hochkamin
EO18: Mast_Antenne

# colnames(shp_2_5_aktuell_all)
# table(shp_2_5_aktuell_all$art)
# table(shp_2_5_aktuell_all$otype)
# table(shp_2_5_aktuell_all$bem)
# shp_2_5_aktuell_all$egid
# 
# 
# aa <- shp_2_5_aktuell_all %>% filter(otype == "EO") %>% st_transform(4326) %>% filter(art == 6)
# table(aa$art)
# 
# m <- leaflet() %>% addTiles() %>%
#                    addPolygons(data = aa, color = "black", weight = 10, fillOpacity = 0.5,
#                                 popup = ~str_c('status: ', sta, "<br>"))
# m

2.4 Daten Check

Es gibt Overlaps der Gebäudegeometrien:
* Geometrien die aneinandergrenzen überlappen sich manchmal minimal –> Kein Problem.
* Bei gewissen Bauten ist sowohl ein “reales” Gebäude erfasst als auch ein Bauprojekt mit bewilligter Genehmigung. Das ist ein Problem für die Auswertung.

Es wird Folgendes gemacht um dieses Problem zu umgehen: * Bei Überlappungen 2012 werden nur bestehende Bauten berücksichtigt (dies entspricht “real” und “erstellt” im sta-Attribut) und aktuell nur die Bauprojekte. Wenn keine Überlappungen herrshen werden reale Gebäude und Bauprojekte berücksichtigt.

#### Data Check
# Auflösen der Überlappungen zwischen existierenden Gebäuden und Bauprojekten.
# Wenn use_fancy=TRUE werden 2012 nur Bestehende Bauten zu berücksichtigen und aktuell nur die Bauprojekte.
# Wenn use_fancy=FALSE werden immer nur die "realen" Bauten berücksichtigt

use_fancy = TRUE
#### Data Check
# Auflösen der Überlappungen zwischen existierenden Geäbuden und Bauprojekten.
# Ziel ist bei Überalppungen, 2012 nur Bestehende Bauten zu berücksichtigen und aktuell nur die Bauprojekte.

if(use_fancy){
  
  quartier_namen <- grenzen$qname
    
  dat_2012_freigegeben <- shp_2_5_2012_all %>% filter(sta == "freigegeben") %>% 
                                               filter(otype == "BB") %>% filter(Quartier %in% quartier_namen)
  dat_2012_real        <- shp_2_5_2012_all %>% filter(sta %in% c("real", "erstellt")) %>% 
                                               filter(otype == "BB") %>% filter(Quartier %in% quartier_namen)
                                               
  dat_aktuell_freigegeben <- shp_2_5_aktuell_all %>% filter(sta == "freigegeben") %>%
                                                     filter(otype == "BB") %>% filter(Quartier %in% quartier_namen)
  dat_aktuell_real        <- shp_2_5_aktuell_all %>% filter(sta  %in% c("real", "erstellt")) %>%
                                                     filter(otype == "BB") %>% filter(Quartier %in% quartier_namen)
  
  
  ### Check intersections zwischen real und freigegebenen Projekten
  
  ## 2012
  complete_2012 <- rbind(dat_2012_real, dat_2012_freigegeben) # Reihenfolge ist wichtig! Erst real, dann freigegeben! Weil die freigegebenen die überlappt werden, werden entfernt!
  
  # loope durch alle Quartiere, viel schneller!
  differences_2012 <- data.frame()
  for (quartier_name in quartier_namen){
    print(quartier_name)
    differences_2012 <- rbind(differences_2012, st_difference(complete_2012[complete_2012$Quartier == quartier_name, ]))
  }
  
  # für graphischen check
  # d_2012_freigegeben <- differences_2012 %>% filter(sta == "freigegeben") %>% filter(Quartier == "Escher Wyss") %>% st_transform(4326)
  # d_2012_real <- differences_2012 %>% filter(sta %in% c("real", "erstellt")) %>% filter(Quartier == "Escher Wyss") %>% st_transform(4326)
  # 
  # # für graphischen check
  # m <- leaflet() %>% addTiles() %>% addPolygons(data = d_2012_freigegeben, color = "purple", opacity = 0.4,
  #                                               popup = ~str_c('status: ', sta, "<br>",
  #                                                              'Traufhöhe: ', h_rel_trau, "<br>",
  #                                                              'EGID: ', egid)) %>%
  #                                   addPolygons(data = d_2012_real, color = "yellow", opacity = 0.4,
  #                                               popup = ~str_c('status: ', sta, "<br>",
  #                                                              'Traufhöhe: ', h_rel_trau, "<br>",
  #                                                              'EGID: ', egid))
  # m
  
  
  ## aktuell
  # Reihenfolge ist wichtig! Erst FREIGEGEBEN dann real! Weil die realen die überlappt werden, werden entfernt!
  complete_aktuell <- rbind(dat_aktuell_freigegeben, dat_aktuell_real)
  
  # loope durch alle Quartiere, viel schneller!
  differences_aktuell <- data.frame()
  for (quartier_name in quartier_namen){
    print(quartier_name)
    differences_aktuell <- rbind(differences_aktuell, st_difference(complete_aktuell[complete_aktuell$Quartier == quartier_name, ]))
    
  }
  
  # für graphischen check
  # d_aktuell_freigegeben <- differences_aktuell %>% filter(sta == "freigegeben") %>% filter(Quartier == "Escher Wyss") %>% st_transform(4326)
  # d_aktuell_real <- differences_aktuell %>% filter(sta == "real") %>% filter(Quartier == "Escher Wyss") %>% st_transform(4326)
  # 
  # m <- leaflet() %>% addTiles() %>% addPolygons(data = d_aktuell_freigegeben, color = "purple", opacity = 0.4,
  #                                               popup = ~str_c('status: ', sta, "<br>",
  #                                                              'Traufhöhe: ', h_rel_trau, "<br>",
  #                                                              'EGID: ', egid)) %>%
  #                                   addPolygons(data = d_aktuell_real, color = "yellow", opacity = 0.4,
  #                                               popup = ~str_c('status: ', sta, "<br>",
  #                                                              'Traufhöhe: ', h_rel_trau, "<br>",
  #                                                              'EGID: ', egid))
  # m
}

3 Analyse Gebäudehöhen

3.1 Veränderung Ø-Gebäudehöhe (ganze Stadt)

Berücksichtigte Gebäude: Siehe Kapitel “Daten Check”.

Die Gebäudehöhen werden gewichtet mit der jeweiligen Grundfläche.

## Übernahme der Daten aus "Daten Check"

if(use_fancy){
  
  buildings_2012 <- differences_2012
  buildings_aktuell <- differences_aktuell
  
} else{
  
## oder einfachere Lösung anwenden, bei Bedarf:
  buildings_2012 <- shp_2_5_2012_all %>% filter(sta %in% c("real", "erstellt")) %>%
                                       filter(otype == "BB")
  buildings_aktuell <- shp_2_5_aktuell_all %>% filter(sta %in% c("real", "erstellt")) %>%
                                             filter(otype == "BB")
}

3.1.1 Firsthöhe

Durchschnittliche Gebäudehöhe in der Ganzen Stadt basierend auf der Firsthöhe:

height_2012_average <- sum(buildings_2012$volume_firs) / sum(buildings_2012$area)
height_aktuell_average <- sum(buildings_aktuell$volume_firs) / sum(buildings_aktuell$area)
dif_height_average <- height_aktuell_average - height_2012_average

print("Firsthöhe: ")
print(str_c("Durchschnittliche Höhe 2012: ", round(height_2012_average, 2), " m"))
print(str_c("Durchschnittliche Höhe Aktuell: ", round(height_aktuell_average, 2), " m"))
print(str_c("Die Stadt ist also heute im Durchschnitt ", round(dif_height_average, 2), " m höher als 2012"))
## [1] "Firsthöhe: "
## [1] "Durchschnittliche Höhe 2012: 15.61 m"
## [1] "Durchschnittliche Höhe Aktuell: 15.82 m"
## [1] "Die Stadt ist also heute im Durchschnitt 0.2 m höher als 2012"

3.1.2 Traufhöhe

Durchschnittliche Gebäudehöhe in der Ganzen Stadt basierend auf der Traufhöhe:

height_2012_average <- sum(buildings_2012$volume_trauf) / sum(buildings_2012$area)
height_aktuell_average <- sum(buildings_aktuell$volume_trauf) / sum(buildings_aktuell$area)
dif_height_average <- height_aktuell_average - height_2012_average

print("Trauffhöhe:")
print(str_c("Durchschnittliche Höhe 2012: ", round(height_2012_average, 2), " m"))
print(str_c("Durchschnittliche Höhe Aktuell: ", round(height_aktuell_average, 2), " m"))
print(str_c("Die Stadt ist also heute im Durchschnitt ", round(dif_height_average, 2), " m höher als 2012"))
## [1] "Trauffhöhe:"
## [1] "Durchschnittliche Höhe 2012: 12.07 m"
## [1] "Durchschnittliche Höhe Aktuell: 12.69 m"
## [1] "Die Stadt ist also heute im Durchschnitt 0.62 m höher als 2012"

3.2 Ø-Gebäudehöhe pro Quartier

Berechnet mit der Firsthöhe der Gebäude, und gewichtet mit der jeweiligen Grundfläche. Tabellen sind nach der durchschnittlichen Firsthöhe sortiert.

3.2.1 Firsthöhe

3.2.1.1 Aktueller Gebäudestand (Firsthöhe)

temp_quartiere_volume <- buildings_aktuell %>% st_drop_geometry() %>% group_by(Quartier) %>% summarise(sum_volume_firs = sum(volume_firs))
temp_quartiere_area <- buildings_aktuell %>% st_drop_geometry() %>% group_by(Quartier) %>% summarise(sum_area = sum(area))

res_quartiere_aktuell <- temp_quartiere_volume %>% left_join(temp_quartiere_area) %>%
                                                   left_join(grenzen, by = c("Quartier" = "qname")) %>% 
                                                   mutate(avg_height_firs = sum_volume_firs / sum_area) 

res_quartiere_aktuell$avg_height_firs <- res_quartiere_aktuell$avg_height_firs

st_geometry(res_quartiere_aktuell) <- st_geometry(res_quartiere_aktuell$geometry)

res_quartiere_aktuell[, "color"] <- "lightgreen"
res_quartiere_aktuell[res_quartiere_aktuell$avg_height_firs > 15, "color"] <- "green"
res_quartiere_aktuell[res_quartiere_aktuell$avg_height_firs > 17, "color"] <- "yellow"
res_quartiere_aktuell[res_quartiere_aktuell$avg_height_firs > 19, "color"] <- "orange"
res_quartiere_aktuell[res_quartiere_aktuell$avg_height_firs > 21, "color"] <- "red"
res_quartiere_aktuell[res_quartiere_aktuell$avg_height_firs > 23, "color"] <- "darkred"

res_quartiere_aktuell %>% st_drop_geometry() %>%
                          dplyr::select(-c("objectid", "objid", "qnr", "knr")) %>% 
                          arrange(-avg_height_firs) %>% 
                          knitr::kable( caption =  "Aktueller Gebäudestand: Durchschnittliche Firsthöhe", digits = 1) %>%
                          kable_styling(bootstrap_options = "striped", full_width = F, fixed_thead = T) %>% 
                          scroll_box(height = "400px", fixed_thead = TRUE)
Aktueller Gebäudestand: Durchschnittliche Firsthöhe
Quartier sum_volume_firs sum_area kname avg_height_firs color
City 4717335 209478.5 Kreis 1 22.5 red
Escher Wyss 9114336 415164.1 Kreis 5 22.0 red
Lindenhof 2339557 107410.1 Kreis 1 21.8 red
Langstrasse 6192741 302957.4 Kreis 4 20.4 orange
Hochschulen 2558738 125915.4 Kreis 1 20.3 orange
Werd 2268007 115313.4 Kreis 4 19.7 orange
Rathaus 2433442 131355.2 Kreis 1 18.5 yellow
Enge 7464714 406079.8 Kreis 2 18.4 yellow
Alt-Wiedikon 8372181 457419.0 Kreis 3 18.3 yellow
Gewerbeschule 4156077 230049.8 Kreis 5 18.1 yellow
Seefeld 2913681 161541.5 Kreis 8 18.0 yellow
Sihlfeld 5800006 332606.3 Kreis 3 17.4 yellow
Oberstrass 5990324 349472.9 Kreis 6 17.1 yellow
Altstetten 15887635 976629.4 Kreis 9 16.3 green
Mühlebach 2998366 184786.6 Kreis 8 16.2 green
Unterstrass 7754058 482970.8 Kreis 6 16.1 green
Wipkingen 4708862 302914.9 Kreis 10 15.5 green
Hard 5189835 334573.3 Kreis 4 15.5 green
Seebach 9670403 630860.8 Kreis 11 15.3 green
Oerlikon 10473289 687434.9 Kreis 11 15.2 green
Hottingen 5829686 385698.2 Kreis 7 15.1 green
Hirslanden 2672641 177554.0 Kreis 7 15.1 green
Fluntern 5002566 343959.4 Kreis 7 14.5 lightgreen
Albisrieden 6366740 455848.4 Kreis 9 14.0 lightgreen
Wollishofen 6871398 507416.4 Kreis 2 13.5 lightgreen
Friesenberg 3161033 236509.7 Kreis 3 13.4 lightgreen
Weinegg 3534756 265270.8 Kreis 8 13.3 lightgreen
Höngg 7793036 598036.0 Kreis 10 13.0 lightgreen
Affoltern 6375219 496236.6 Kreis 11 12.8 lightgreen
Hirzenbach 2671110 213022.3 Kreis 12 12.5 lightgreen
Saatlen 2145878 172138.9 Kreis 12 12.5 lightgreen
Leimbach 1430379 115088.3 Kreis 2 12.4 lightgreen
Schwamendingen-Mitte 2561141 208332.9 Kreis 12 12.3 lightgreen
Witikon 3288538 305382.0 Kreis 7 10.8 lightgreen

3.2.1.2 2012 Gebäudestand (Firsthöhe)

temp_quartiere_volume <- buildings_2012 %>% st_drop_geometry() %>% group_by(Quartier) %>% summarise(sum_volume_firs = sum(volume_firs))
temp_quartiere_area <- buildings_2012 %>% st_drop_geometry() %>% group_by(Quartier) %>% summarise(sum_area = sum(area))

res_quartiere_2012 <- temp_quartiere_volume %>% left_join(temp_quartiere_area) %>%
                                                   left_join(grenzen, by = c("Quartier" = "qname")) %>% 
                                                   mutate(avg_height_firs = sum_volume_firs / sum_area) 

res_quartiere_2012$avg_height_firs <- res_quartiere_2012$avg_height_firs

st_geometry(res_quartiere_2012) <- st_geometry(res_quartiere_aktuell$geometry)

res_quartiere_2012[, "color"] <- "lightgreen"
res_quartiere_2012[res_quartiere_2012$avg_height_firs > 15, "color"] <- "green"
res_quartiere_2012[res_quartiere_2012$avg_height_firs > 17, "color"] <- "yellow"
res_quartiere_2012[res_quartiere_2012$avg_height_firs > 19, "color"] <- "orange"
res_quartiere_2012[res_quartiere_2012$avg_height_firs > 21, "color"] <- "red"
res_quartiere_2012[res_quartiere_2012$avg_height_firs > 23, "color"] <- "darkred"

res_quartiere_2012 %>% st_drop_geometry() %>%
                       dplyr::select(-c("objectid", "objid", "qnr", "knr")) %>% 
                       arrange(-avg_height_firs) %>% 
                       knitr::kable( caption =  "Gebäudestand 2012: Durchschnittliche Firsthöhe", digits = 1) %>%
                       kable_styling(bootstrap_options = "striped", full_width = F, fixed_thead = T) %>% 
                       scroll_box(height = "400px", fixed_thead = TRUE)
Gebäudestand 2012: Durchschnittliche Firsthöhe
Quartier sum_volume_firs sum_area kname avg_height_firs color
City 4753217 207489.4 Kreis 1 22.9 red
Lindenhof 2369492 107428.3 Kreis 1 22.1 red
Escher Wyss 8710222 408649.0 Kreis 5 21.3 red
Hochschulen 2600855 123859.6 Kreis 1 21.0 orange
Werd 2247893 112975.9 Kreis 4 19.9 orange
Langstrasse 5559638 279628.6 Kreis 4 19.9 orange
Rathaus 2433001 130747.1 Kreis 1 18.6 yellow
Enge 7217865 393440.0 Kreis 2 18.3 yellow
Gewerbeschule 4105910 226227.2 Kreis 5 18.1 yellow
Alt-Wiedikon 8019657 445421.1 Kreis 3 18.0 yellow
Seefeld 2801408 155967.3 Kreis 8 18.0 yellow
Oberstrass 5784543 331959.4 Kreis 6 17.4 yellow
Sihlfeld 5578941 326160.5 Kreis 3 17.1 yellow
Mühlebach 2910565 178598.2 Kreis 8 16.3 green
Unterstrass 7246978 455601.6 Kreis 6 15.9 green
Wipkingen 4610431 293442.8 Kreis 10 15.7 green
Altstetten 14338390 913470.6 Kreis 9 15.7 green
Hottingen 5962343 382202.7 Kreis 7 15.6 green
Hirslanden 2614081 172690.2 Kreis 7 15.1 green
Oerlikon 9898556 656090.0 Kreis 11 15.1 green
Hard 4818172 325856.9 Kreis 4 14.8 lightgreen
Fluntern 4774123 327918.6 Kreis 7 14.6 lightgreen
Seebach 8563823 588783.8 Kreis 11 14.5 lightgreen
Weinegg 3049381 229082.1 Kreis 8 13.3 lightgreen
Albisrieden 5694688 427814.1 Kreis 9 13.3 lightgreen
Friesenberg 3003618 229089.6 Kreis 3 13.1 lightgreen
Affoltern 5943337 457437.1 Kreis 11 13.0 lightgreen
Höngg 7257170 559942.8 Kreis 10 13.0 lightgreen
Wollishofen 6333826 493527.0 Kreis 2 12.8 lightgreen
Schwamendingen-Mitte 2555683 212074.7 Kreis 12 12.1 lightgreen
Leimbach 1273073 106251.4 Kreis 2 12.0 lightgreen
Hirzenbach 2251437 194645.5 Kreis 12 11.6 lightgreen
Saatlen 1696391 149898.5 Kreis 12 11.3 lightgreen
Witikon 3091332 289263.0 Kreis 7 10.7 lightgreen

3.2.1.3 Veränderung 2012 bis heute (Firsthöhe)

Differenz der durchschnittlichen Firsthöhe zwischen 2012 und heute (Stand Juli 2020).

rot/orange: Zunahme der Gebäudehöhe
Grün: Abnahme der Gebäudehöhe

res_quartiere_dif_firs <- res_quartiere_2012 %>% dplyr::select(c("Quartier", "objectid", "objid", "qnr", "knr", "kname", "geometry"))
res_quartiere_dif_firs[, "avg_height_firs_2012"] <- st_drop_geometry(res_quartiere_2012[, "avg_height_firs"])
res_quartiere_dif_firs[, "avg_height_firs_aktuell"] <- st_drop_geometry(res_quartiere_aktuell[, "avg_height_firs"])

# increase:
res_quartiere_dif_firs <- res_quartiere_dif_firs %>% mutate(avg_height_firs_increase = avg_height_firs_aktuell - avg_height_firs_2012)

# increase in percent:
res_quartiere_dif_firs <- res_quartiere_dif_firs %>% mutate(increase_firs_percent = avg_height_firs_increase/avg_height_firs_2012*100)

# Farben für Grafik 
res_quartiere_dif_firs[, "color"] <- "green"
res_quartiere_dif_firs[res_quartiere_dif_firs$avg_height_firs_increase > -0.25, "color"] <- "white"
res_quartiere_dif_firs[res_quartiere_dif_firs$avg_height_firs_increase > +0.25, "color"] <- "orange"
res_quartiere_dif_firs[res_quartiere_dif_firs$avg_height_firs_increase > +0.75, "color"] <- "red"
res_quartiere_dif_firs[res_quartiere_dif_firs$avg_height_firs_increase > +1.25, "color"] <- "darkred"


## Tabelle 
res_quartiere_dif_firs %>% st_drop_geometry() %>%
                           dplyr::select(-c("objectid", "objid", "qnr", "knr")) %>% 
                           arrange(-avg_height_firs_increase) %>% 
                           knitr::kable(caption =  "Veränderung der durchschnittliche Firsthöhe in Metern", digits = 1,
                                        col.names = c("Quartier", "kname", 
                                                      "Ø-Höhe 2012", "Ø-Höhe aktuell", "Erhöhung", "Erhöhung %", "Farbe")) %>%
                           kable_styling(bootstrap_options = "striped", full_width = F, fixed_thead = T) %>% 
                           scroll_box(height = "400px", fixed_thead = TRUE)
Veränderung der durchschnittliche Firsthöhe in Metern
Quartier kname Ø-Höhe 2012 Ø-Höhe aktuell Erhöhung Erhöhung % Farbe
Saatlen Kreis 12 11.3 12.5 1.1 10.2 red
Hirzenbach Kreis 12 11.6 12.5 1.0 8.4 red
Seebach Kreis 11 14.5 15.3 0.8 5.4 red
Hard Kreis 4 14.8 15.5 0.7 4.9 orange
Wollishofen Kreis 2 12.8 13.5 0.7 5.5 orange
Albisrieden Kreis 9 13.3 14.0 0.7 4.9 orange
Escher Wyss Kreis 5 21.3 22.0 0.6 3.0 orange
Altstetten Kreis 9 15.7 16.3 0.6 3.6 orange
Langstrasse Kreis 4 19.9 20.4 0.6 2.8 orange
Leimbach Kreis 2 12.0 12.4 0.4 3.7 orange
Sihlfeld Kreis 3 17.1 17.4 0.3 1.9 orange
Alt-Wiedikon Kreis 3 18.0 18.3 0.3 1.7 orange
Friesenberg Kreis 3 13.1 13.4 0.3 1.9 orange
Schwamendingen-Mitte Kreis 12 12.1 12.3 0.2 2.0 white
Unterstrass Kreis 6 15.9 16.1 0.1 0.9 white
Oerlikon Kreis 11 15.1 15.2 0.1 1.0 white
Witikon Kreis 7 10.7 10.8 0.1 0.8 white
Seefeld Kreis 8 18.0 18.0 0.1 0.4 white
Höngg Kreis 10 13.0 13.0 0.1 0.5 white
Enge Kreis 2 18.3 18.4 0.0 0.2 white
Weinegg Kreis 8 13.3 13.3 0.0 0.1 white
Fluntern Kreis 7 14.6 14.5 0.0 -0.1 white
Mühlebach Kreis 8 16.3 16.2 -0.1 -0.4 white
Rathaus Kreis 1 18.6 18.5 -0.1 -0.4 white
Gewerbeschule Kreis 5 18.1 18.1 -0.1 -0.5 white
Hirslanden Kreis 7 15.1 15.1 -0.1 -0.6 white
Affoltern Kreis 11 13.0 12.8 -0.1 -1.1 white
Wipkingen Kreis 10 15.7 15.5 -0.2 -1.1 white
Werd Kreis 4 19.9 19.7 -0.2 -1.2 white
Lindenhof Kreis 1 22.1 21.8 -0.3 -1.2 green
Oberstrass Kreis 6 17.4 17.1 -0.3 -1.6 green
City Kreis 1 22.9 22.5 -0.4 -1.7 green
Hottingen Kreis 7 15.6 15.1 -0.5 -3.1 green
Hochschulen Kreis 1 21.0 20.3 -0.7 -3.2 green
## Plot
df_plot <- res_quartiere_dif_firs %>% st_transform(4326)

m <- leaflet() %>% addTiles() %>%
                   addPolygons(data = df_plot, color = "black", fillColor  = ~color, weight = 2, fillOpacity = 0.5,
                               popup = ~str_c('Durchschnittliche Firsthöhe Heute: ', round(avg_height_firs_aktuell, 1), " m", "<br>",
                                              'Durchschnittliche Erhöhung 2012 bis heute: ', round(avg_height_firs_increase, 1), " m", "<br>",
                                              "Quartier: ", Quartier))
m

3.2.2 Traufhöhe:

3.2.2.1 Aktueller Gebäudestand (Traufhöhe)

temp_quartiere_volume <- buildings_aktuell %>% st_drop_geometry() %>% group_by(Quartier) %>% summarise(sum_volume_trauf = sum(volume_trauf))
temp_quartiere_area <- buildings_aktuell %>% st_drop_geometry() %>% group_by(Quartier) %>% summarise(sum_area = sum(area))

res_quartiere_aktuell <- temp_quartiere_volume %>% left_join(temp_quartiere_area) %>%
                                                   left_join(grenzen, by = c("Quartier" = "qname")) %>% 
                                                   mutate(avg_height_trauf = sum_volume_trauf / sum_area) 

res_quartiere_aktuell$avg_height_trauf <- res_quartiere_aktuell$avg_height_trauf

st_geometry(res_quartiere_aktuell) <- st_geometry(res_quartiere_aktuell$geometry)

res_quartiere_aktuell[, "color"] <- "lightgreen"
res_quartiere_aktuell[res_quartiere_aktuell$avg_height_trauf > 15, "color"] <- "green"
res_quartiere_aktuell[res_quartiere_aktuell$avg_height_trauf > 17, "color"] <- "yellow"
res_quartiere_aktuell[res_quartiere_aktuell$avg_height_trauf > 19, "color"] <- "orange"
res_quartiere_aktuell[res_quartiere_aktuell$avg_height_trauf > 21, "color"] <- "red"
res_quartiere_aktuell[res_quartiere_aktuell$avg_height_trauf > 23, "color"] <- "darkred"

res_quartiere_aktuell %>% st_drop_geometry() %>%
                       dplyr::select(-c("objectid", "objid", "qnr", "knr")) %>% 
                       arrange(-avg_height_trauf) %>% 
                       knitr::kable(caption =  "Aktueller Gebäudestand: Durchschnittliche Traufhöhe",
                                    digits = 1) %>%
                       kable_styling(bootstrap_options = "striped", full_width = F, fixed_thead = T) %>% 
                       scroll_box(height = "400px", fixed_thead = TRUE)
Aktueller Gebäudestand: Durchschnittliche Traufhöhe
Quartier sum_volume_trauf sum_area kname avg_height_trauf color
Escher Wyss 8104693 415164.1 Kreis 5 19.5 orange
City 3636940 209478.5 Kreis 1 17.4 yellow
Langstrasse 5030099 302957.4 Kreis 4 16.6 green
Lindenhof 1768884 107410.1 Kreis 1 16.5 green
Hochschulen 1972535 125915.4 Kreis 1 15.7 green
Werd 1753160 115313.4 Kreis 4 15.2 green
Alt-Wiedikon 6903059 457419.0 Kreis 3 15.1 green
Enge 5659841 406079.8 Kreis 2 13.9 lightgreen
Gewerbeschule 3184717 230049.8 Kreis 5 13.8 lightgreen
Seebach 8714283 630860.8 Kreis 11 13.8 lightgreen
Sihlfeld 4541625 332606.3 Kreis 3 13.7 lightgreen
Altstetten 13278110 976629.4 Kreis 9 13.6 lightgreen
Rathaus 1783011 131355.2 Kreis 1 13.6 lightgreen
Seefeld 2191028 161541.5 Kreis 8 13.6 lightgreen
Oerlikon 8908534 687434.9 Kreis 11 13.0 lightgreen
Hard 4255882 334573.3 Kreis 4 12.7 lightgreen
Oberstrass 4407770 349472.9 Kreis 6 12.6 lightgreen
Mühlebach 2264540 184786.6 Kreis 8 12.3 lightgreen
Unterstrass 5854263 482970.8 Kreis 6 12.1 lightgreen
Albisrieden 5246881 455848.4 Kreis 9 11.5 lightgreen
Wipkingen 3481934 302914.9 Kreis 10 11.5 lightgreen
Saatlen 1921934 172138.9 Kreis 12 11.2 lightgreen
Hirzenbach 2347305 213022.3 Kreis 12 11.0 lightgreen
Fluntern 3730057 343959.4 Kreis 7 10.8 lightgreen
Friesenberg 2562443 236509.7 Kreis 3 10.8 lightgreen
Hottingen 4166328 385698.2 Kreis 7 10.8 lightgreen
Affoltern 5267791 496236.6 Kreis 11 10.6 lightgreen
Wollishofen 5340922 507416.4 Kreis 2 10.5 lightgreen
Höngg 6244638 598036.0 Kreis 10 10.4 lightgreen
Hirslanden 1839704 177554.0 Kreis 7 10.4 lightgreen
Weinegg 2740162 265270.8 Kreis 8 10.3 lightgreen
Schwamendingen-Mitte 2149301 208332.9 Kreis 12 10.3 lightgreen
Leimbach 1165321 115088.3 Kreis 2 10.1 lightgreen
Witikon 2549095 305382.0 Kreis 7 8.3 lightgreen

3.2.2.2 2012 Gebäudestand (Traufhöhe)

temp_quartiere_volume <- buildings_2012 %>% st_drop_geometry() %>% group_by(Quartier) %>% summarise(sum_volume_trauf = sum(volume_trauf))
temp_quartiere_area <- buildings_2012 %>% st_drop_geometry() %>% group_by(Quartier) %>% summarise(sum_area = sum(area))

res_quartiere_2012 <- temp_quartiere_volume %>% left_join(temp_quartiere_area) %>%
                                                   left_join(grenzen, by = c("Quartier" = "qname")) %>% 
                                                   mutate(avg_height_trauf = sum_volume_trauf / sum_area) 

res_quartiere_2012$avg_height_trauf <- res_quartiere_2012$avg_height_trauf

st_geometry(res_quartiere_2012) <- st_geometry(res_quartiere_aktuell$geometry)

res_quartiere_2012[, "color"] <- "lightgreen"
res_quartiere_2012[res_quartiere_2012$avg_height_trauf > 15, "color"] <- "green"
res_quartiere_2012[res_quartiere_2012$avg_height_trauf > 17, "color"] <- "yellow"
res_quartiere_2012[res_quartiere_2012$avg_height_trauf > 19, "color"] <- "orange"
res_quartiere_2012[res_quartiere_2012$avg_height_trauf > 21, "color"] <- "red"
res_quartiere_2012[res_quartiere_2012$avg_height_trauf > 23, "color"] <- "darkred"

res_quartiere_2012 %>% st_drop_geometry() %>%
                       dplyr::select(-c("objectid", "objid", "qnr", "knr")) %>% 
                       arrange(-avg_height_trauf) %>% 
                       knitr::kable( caption =  "Gebäudestand 2012: Durchschnittliche Traufhöhe", digits = 1) %>%
                       kable_styling(bootstrap_options = "striped", full_width = F, fixed_thead = T) %>% 
                       scroll_box(height = "400px", fixed_thead = TRUE)
Gebäudestand 2012: Durchschnittliche Traufhöhe
Quartier sum_volume_trauf sum_area kname avg_height_trauf color
Escher Wyss 7535886 408649.0 Kreis 5 18.4 yellow
City 3588447 207489.4 Kreis 1 17.3 yellow
Lindenhof 1764781 107428.3 Kreis 1 16.4 green
Langstrasse 4395559 279628.6 Kreis 4 15.7 green
Hochschulen 1897755 123859.6 Kreis 1 15.3 green
Werd 1713959 112975.9 Kreis 4 15.2 green
Alt-Wiedikon 6448343 445421.1 Kreis 3 14.5 lightgreen
Gewerbeschule 3118003 226227.2 Kreis 5 13.8 lightgreen
Rathaus 1778719 130747.1 Kreis 1 13.6 lightgreen
Enge 5274200 393440.0 Kreis 2 13.4 lightgreen
Seefeld 2062392 155967.3 Kreis 8 13.2 lightgreen
Sihlfeld 4264197 326160.5 Kreis 3 13.1 lightgreen
Seebach 7539861 588783.8 Kreis 11 12.8 lightgreen
Oerlikon 8284751 656090.0 Kreis 11 12.6 lightgreen
Oberstrass 4177853 331959.4 Kreis 6 12.6 lightgreen
Altstetten 11207043 913470.6 Kreis 9 12.3 lightgreen
Mühlebach 2160592 178598.2 Kreis 8 12.1 lightgreen
Hard 3736141 325856.9 Kreis 4 11.5 lightgreen
Unterstrass 5217015 455601.6 Kreis 6 11.5 lightgreen
Wipkingen 3321147 293442.8 Kreis 10 11.3 lightgreen
Hottingen 4218718 382202.7 Kreis 7 11.0 lightgreen
Fluntern 3433600 327918.6 Kreis 7 10.5 lightgreen
Friesenberg 2381624 229089.6 Kreis 3 10.4 lightgreen
Albisrieden 4417105 427814.1 Kreis 9 10.3 lightgreen
Hirslanden 1764335 172690.2 Kreis 7 10.2 lightgreen
Affoltern 4660662 457437.1 Kreis 11 10.2 lightgreen
Höngg 5627411 559942.8 Kreis 10 10.0 lightgreen
Schwamendingen-Mitte 2117692 212074.7 Kreis 12 10.0 lightgreen
Hirzenbach 1902121 194645.5 Kreis 12 9.8 lightgreen
Saatlen 1443410 149898.5 Kreis 12 9.6 lightgreen
Weinegg 2179419 229082.1 Kreis 8 9.5 lightgreen
Leimbach 1009814 106251.4 Kreis 2 9.5 lightgreen
Wollishofen 4509723 493527.0 Kreis 2 9.1 lightgreen
Witikon 2353183 289263.0 Kreis 7 8.1 lightgreen

3.2.2.3 Veränderung 2012 bis heute (Traufhöhe)

Differenz der durchschnittlichen Traufhöhe zwischen 2012 und heute (Stand Juli 2020).

rot/orange: Zunahme der Gebäudehöhe
Grün: Abnahme der Gebäudehöhe

res_quartiere_dif_trauf <- res_quartiere_2012 %>% dplyr::select(c("Quartier", "objectid", "objid", "qnr", "knr", "kname", "geometry"))
res_quartiere_dif_trauf[, "avg_height_trauf_2012"] <- st_drop_geometry(res_quartiere_2012[, "avg_height_trauf"])
res_quartiere_dif_trauf[, "avg_height_trauf_aktuell"] <- st_drop_geometry(res_quartiere_aktuell[, "avg_height_trauf"])

# increase:
res_quartiere_dif_trauf <- res_quartiere_dif_trauf %>% mutate(avg_height_trauf_increase = avg_height_trauf_aktuell - avg_height_trauf_2012)

# increase in percent:
res_quartiere_dif_trauf <- res_quartiere_dif_trauf %>% mutate(increase_trauf_percent = avg_height_trauf_increase/avg_height_trauf_2012*100)

# Farben für Grafik 
res_quartiere_dif_trauf[, "color"] <- "green"
res_quartiere_dif_trauf[res_quartiere_dif_trauf$avg_height_trauf_increase > -0.25, "color"] <- "white"
res_quartiere_dif_trauf[res_quartiere_dif_trauf$avg_height_trauf_increase > +0.25, "color"] <- "orange"
res_quartiere_dif_trauf[res_quartiere_dif_trauf$avg_height_trauf_increase > +0.75, "color"] <- "red"
res_quartiere_dif_trauf[res_quartiere_dif_trauf$avg_height_trauf_increase > +1.25, "color"] <- "darkred"

## Tabelle 
res_quartiere_dif_trauf %>% st_drop_geometry() %>%
                       dplyr::select(-c("objectid", "objid", "qnr", "knr")) %>% 
                       arrange(-avg_height_trauf_increase) %>% 
                       knitr::kable(caption =  "Veränderung der durchschnittliche Traufhöhe in Metern", digits = 1,
                                    col.names = c("Quartier", "kname", 
                                                  "Ø-Höhe 2012", "Ø-Höhe aktuell", "Erhöhung", "Erhöhung %", "Farbe")) %>%
                       kable_styling(bootstrap_options = "striped", full_width = F, fixed_thead = T) %>% 
                       scroll_box(height = "400px", fixed_thead = TRUE)
Veränderung der durchschnittliche Traufhöhe in Metern
Quartier kname Ø-Höhe 2012 Ø-Höhe aktuell Erhöhung Erhöhung % Farbe
Saatlen Kreis 12 9.6 11.2 1.5 15.9 darkred
Wollishofen Kreis 2 9.1 10.5 1.4 15.2 darkred
Altstetten Kreis 9 12.3 13.6 1.3 10.8 darkred
Hard Kreis 4 11.5 12.7 1.3 10.9 darkred
Hirzenbach Kreis 12 9.8 11.0 1.2 12.8 red
Albisrieden Kreis 9 10.3 11.5 1.2 11.5 red
Escher Wyss Kreis 5 18.4 19.5 1.1 5.9 red
Seebach Kreis 11 12.8 13.8 1.0 7.9 red
Langstrasse Kreis 4 15.7 16.6 0.9 5.6 red
Weinegg Kreis 8 9.5 10.3 0.8 8.6 red
Unterstrass Kreis 6 11.5 12.1 0.7 5.9 orange
Leimbach Kreis 2 9.5 10.1 0.6 6.5 orange
Alt-Wiedikon Kreis 3 14.5 15.1 0.6 4.2 orange
Sihlfeld Kreis 3 13.1 13.7 0.6 4.4 orange
Enge Kreis 2 13.4 13.9 0.5 4.0 orange
Friesenberg Kreis 3 10.4 10.8 0.4 4.2 orange
Affoltern Kreis 11 10.2 10.6 0.4 4.2 orange
Höngg Kreis 10 10.0 10.4 0.4 3.9 orange
Fluntern Kreis 7 10.5 10.8 0.4 3.6 orange
Hochschulen Kreis 1 15.3 15.7 0.3 2.2 orange
Seefeld Kreis 8 13.2 13.6 0.3 2.6 orange
Oerlikon Kreis 11 12.6 13.0 0.3 2.6 orange
Schwamendingen-Mitte Kreis 12 10.0 10.3 0.3 3.3 orange
Witikon Kreis 7 8.1 8.3 0.2 2.6 white
Wipkingen Kreis 10 11.3 11.5 0.2 1.6 white
Mühlebach Kreis 8 12.1 12.3 0.2 1.3 white
Hirslanden Kreis 7 10.2 10.4 0.1 1.4 white
City Kreis 1 17.3 17.4 0.1 0.4 white
Gewerbeschule Kreis 5 13.8 13.8 0.1 0.4 white
Lindenhof Kreis 1 16.4 16.5 0.0 0.2 white
Werd Kreis 4 15.2 15.2 0.0 0.2 white
Oberstrass Kreis 6 12.6 12.6 0.0 0.2 white
Rathaus Kreis 1 13.6 13.6 0.0 -0.2 white
Hottingen Kreis 7 11.0 10.8 -0.2 -2.1 white
## Plot
df_plot <- res_quartiere_dif_trauf %>% st_transform(4326)

m <- leaflet() %>% addTiles() %>%
                   addPolygons(data = df_plot, color = "black", fillColor  = ~color, weight = 2, fillOpacity = 0.5,
                               popup = ~str_c('Durchschnittliche Traufhöhe Heute: ', round(avg_height_trauf_aktuell, 1), " m", "<br>",
                                              'Durchschnittliche Erhöhung 2012 bis heute: ', round(avg_height_trauf_increase, 1), " m", "<br>",
                                              "Quartier: ", Quartier))

m

3.2.3 Traufhöhe vs. Firsthöhe

res_quartier_dif <- res_quartiere_dif_trauf %>% select(-c("color", "increase_trauf_percent")) %>% 
                                 left_join(st_drop_geometry(res_quartiere_dif_firs)[, c(
                                                                                        "avg_height_firs_2012", "avg_height_firs_aktuell", 
                                                                                        "avg_height_firs_increase",
                                                                                        "Quartier")], by = "Quartier")


colnames(res_quartier_dif)
##  [1] "Quartier"                  "objectid"                 
##  [3] "objid"                     "qnr"                      
##  [5] "knr"                       "kname"                    
##  [7] "geometry"                  "avg_height_trauf_2012"    
##  [9] "avg_height_trauf_aktuell"  "avg_height_trauf_increase"
## [11] "avg_height_firs_2012"      "avg_height_firs_aktuell"  
## [13] "avg_height_firs_increase"
res_quartier_dif %>% st_drop_geometry() %>%
                     dplyr::select(-c("objectid", "objid", "qnr", "knr")) %>% 
                     arrange(-avg_height_trauf_increase) %>% 
                     knitr::kable(caption =  "Veränderung der durchschnittlichen Gebäudehöhe in Metern", digits = 1,
                                  col.names = c("Quartier", "kname", 
                                                "Höhe 2012", 
                                                "Höhe Aktuell", 
                                                "Erhöhung",
                                                "Höhe 2012",
                                                "Höhe Aktuell",
                                                "Erhöhung")) %>%
                     kable_styling(bootstrap_options = "striped", full_width = F, fixed_thead = T) %>% 
                     add_header_above(c(" ", " ", "Traufhöhe" = 3, "Firsthöhe" = 3)) %>% 
                     scroll_box(height = "400px", fixed_thead = TRUE)
Veränderung der durchschnittlichen Gebäudehöhe in Metern
Traufhöhe
Firsthöhe
Quartier kname Höhe 2012 Höhe Aktuell Erhöhung Höhe 2012 Höhe Aktuell Erhöhung
Saatlen Kreis 12 9.6 11.2 1.5 11.3 12.5 1.1
Wollishofen Kreis 2 9.1 10.5 1.4 12.8 13.5 0.7
Altstetten Kreis 9 12.3 13.6 1.3 15.7 16.3 0.6
Hard Kreis 4 11.5 12.7 1.3 14.8 15.5 0.7
Hirzenbach Kreis 12 9.8 11.0 1.2 11.6 12.5 1.0
Albisrieden Kreis 9 10.3 11.5 1.2 13.3 14.0 0.7
Escher Wyss Kreis 5 18.4 19.5 1.1 21.3 22.0 0.6
Seebach Kreis 11 12.8 13.8 1.0 14.5 15.3 0.8
Langstrasse Kreis 4 15.7 16.6 0.9 19.9 20.4 0.6
Weinegg Kreis 8 9.5 10.3 0.8 13.3 13.3 0.0
Unterstrass Kreis 6 11.5 12.1 0.7 15.9 16.1 0.1
Leimbach Kreis 2 9.5 10.1 0.6 12.0 12.4 0.4
Alt-Wiedikon Kreis 3 14.5 15.1 0.6 18.0 18.3 0.3
Sihlfeld Kreis 3 13.1 13.7 0.6 17.1 17.4 0.3
Enge Kreis 2 13.4 13.9 0.5 18.3 18.4 0.0
Friesenberg Kreis 3 10.4 10.8 0.4 13.1 13.4 0.3
Affoltern Kreis 11 10.2 10.6 0.4 13.0 12.8 -0.1
Höngg Kreis 10 10.0 10.4 0.4 13.0 13.0 0.1
Fluntern Kreis 7 10.5 10.8 0.4 14.6 14.5 0.0
Hochschulen Kreis 1 15.3 15.7 0.3 21.0 20.3 -0.7
Seefeld Kreis 8 13.2 13.6 0.3 18.0 18.0 0.1
Oerlikon Kreis 11 12.6 13.0 0.3 15.1 15.2 0.1
Schwamendingen-Mitte Kreis 12 10.0 10.3 0.3 12.1 12.3 0.2
Witikon Kreis 7 8.1 8.3 0.2 10.7 10.8 0.1
Wipkingen Kreis 10 11.3 11.5 0.2 15.7 15.5 -0.2
Mühlebach Kreis 8 12.1 12.3 0.2 16.3 16.2 -0.1
Hirslanden Kreis 7 10.2 10.4 0.1 15.1 15.1 -0.1
City Kreis 1 17.3 17.4 0.1 22.9 22.5 -0.4
Gewerbeschule Kreis 5 13.8 13.8 0.1 18.1 18.1 -0.1
Lindenhof Kreis 1 16.4 16.5 0.0 22.1 21.8 -0.3
Werd Kreis 4 15.2 15.2 0.0 19.9 19.7 -0.2
Oberstrass Kreis 6 12.6 12.6 0.0 17.4 17.1 -0.3
Rathaus Kreis 1 13.6 13.6 0.0 18.6 18.5 -0.1
Hottingen Kreis 7 11.0 10.8 -0.2 15.6 15.1 -0.5

3.3 Veränderungen auf Gebäude-Ebene

Hier werden ebenfalls nur die “Bodenbebauungs-” Gebäude verwendet. Für die farbige Darstellung der Veränderung der Bauhöhen wird die Datengrundlage wie bei den Analysen weiter oben verwendet.

Die schwarz gezeichneten Grundrisse entsprechen immer den real existierenden Gebäuden im aktuellen Zustand, ohne projektierte Bauten (da dies am ehesten dem Bild entspricht das sich zur Zeit dem Leser zeigt). Zusätzlich werden zur besseren Lesbarkeit die Umrisse ALLER existierenden Bauten gezeichnet, also auch von Brücken und ähnlichen Bauten die in der Analyse nicht berücksichtigt werden.

## Funktion um Rasterkarten zu speichern oder anzuzeigen
# 
# quartier_name <- grenzen$qnam
# quartier_name <- c("Wollishofen", "Leimbach")
# 
# 
# quartier_name <- "Altstetten"
# file_name <- "Saatlen"
# status <-  c("real", "erstellt", "freigegeben")
# status <-  c("real")
# store_switch <- TRUE
# building_type <- "BB"

store_png_scale <- function(quartier_name, file_name, store_switch){
  
  # Gebäudetyp (BB oder EO) und Status wird bereits oben (Daten Check) ausgewählt
  a = buildings_2012    %>% filter(Quartier %in% quartier_name) %>% st_cast("POLYGON")
  b = buildings_aktuell %>% filter(Quartier %in% quartier_name) %>% st_cast("POLYGON")
  
  table(a$sta)
  table(b$sta)
  
  ## Dargestellte Gebäude
  vector_buildings <- shp_2_5_aktuell_all %>% filter(sta %in% c("real", "erstellt")) %>% 
                                              filter(Quartier %in% quartier_name)

  vector_planned <-   shp_2_5_aktuell_all %>% filter(sta %in% c("freigegeben")) %>% 
                                              filter(Quartier %in% quartier_name)
  
  vector_grenzen <- grenzen %>% filter(qname %in% quartier_name)

  ## Dargestellte Grundrisse
  
  
  ## Erstelle Raster
  
  r_2012 <- raster(a, res = 1)
  r_aktuell <- raster(b, res = 1)

  ## Origin anpassen sonst Fehler (Wieso?)
  origin(r_2012) <- c(0, 0)
  origin(r_aktuell) <- c(0, 0)
  
  r_2012 <- a %>% fasterize(r_2012, field = "h_rel_trau", fun="sum")
  r_aktuell <- b %>% fasterize(r_aktuell, field = "h_rel_trau", fun="sum")
  
  r_2012@data@values[is.na(r_2012@data@values)] <- 0
  r_aktuell@data@values[is.na(r_aktuell@data@values)] <- 0
  
  ## Differenz
  r_dif <- r_aktuell - r_2012

  
  ## Speichern und darstellen
  if(store_switch){
    png(paste(file_name, "_2012-heute", '.png',sep=''),width=r_dif@ncols,height=r_dif@nrows)
  }
  
  cuts=c(130, 10, 2, -2, -10, -130) #set breaks
  # colors <- brewer.pal(5, "BrBG")
  colors <- c("#8c510a","#dfc27d", "#00000000", "#80cdc1", "#01665e")
  colors[3] <- "#00000000"
  
  plot(r_dif, maxpixels=r_dif@ncols*r_dif@nrows, breaks=cuts, col = colors) # main = " "
  plot(vector_buildings$geometry, add = TRUE)
  plot(vector_grenzen$geometry, color = "blue", add = TRUE)
  if(store_switch){
    dev.off()
  }
}


# # Generiere PNGs von allen Quartieren nur bei Bedarf aktivieren
# for (i in 1:length(grenzen$qname)){
#   quartier <- grenzen$qname[i]
#   print(quartier)
#   store_png_scale(quartier, str_c(quartier, "_inkl_proj"), TRUE)
# 
# }

3.4 Leaflet Plots

prep_leaflet_plots <- function(quartier_name, file_name){
  
  # Gebäudetyp (BB oder EO) und Status wird bereits oben (Daten Check) ausgewählt
  a = buildings_2012    %>% filter(Quartier %in% quartier_name) %>% st_cast("POLYGON")
  b = buildings_aktuell %>% filter(Quartier %in% quartier_name) %>% st_cast("POLYGON")
  
  table(a$sta)
  table(b$sta)
  
  ## Dargestellte Gebäude
  vector_buildings <- shp_2_5_aktuell_all %>% filter(sta %in% c("real", "erstellt")) %>% 
                                              filter(Quartier %in% quartier_name)

  vector_planned <-   shp_2_5_aktuell_all %>% filter(sta %in% c("freigegeben")) %>% 
                                              filter(Quartier %in% quartier_name)
  
  vector_grenzen <- grenzen %>% filter(qname %in% quartier_name)

  ## Dargestellte Grundrisse
  
  
  ## Erstelle Raster
  
  r_2012 <- raster(a, res = 1)
  r_aktuell <- raster(b, res = 1)

  ## Origin anpassen sonst Fehler (Wieso?)
  origin(r_2012) <- c(0, 0)
  origin(r_aktuell) <- c(0, 0)
  
  r_2012 <- a %>% fasterize(r_2012, field = "h_rel_trau", fun="sum")
  r_aktuell <- b %>% fasterize(r_aktuell, field = "h_rel_trau", fun="sum")
  
  r_2012@data@values[is.na(r_2012@data@values)] <- 0
  r_aktuell@data@values[is.na(r_aktuell@data@values)] <- 0
  
  ## Differenz
  r_dif <<- r_aktuell - r_2012

  ## Def Farben
  cuts <- c(130, 10, 2, -2, -10, -130) #set breaks
  colors_plot <<- c("#8c510a","#dfc27d", "#00000000", "#80cdc1", "#01665e")
  # colors_plot[3] <- "#00000000"
  col_pal <<- colorBin(colors_plot, domain = c(-130, 130), bins = cuts, na.color = "#00000000")

  ## Plot mit leaflet()
    
  vector_buildings[vector_buildings$sta == "erstellt", "sta"] <- "Gebaut"
  vector_buildings[vector_buildings$sta == "real", "sta"] <- "Gebaut"
  vector_planned[vector_planned$sta == "freigegeben", "sta"] <- "Geplant"
  
  table(vector_planned$sta)
  
  df_buildings <<- vector_buildings %>% st_transform(4326)
  df_planned <<- vector_planned %>% st_transform(4326)
  df_borders <<- vector_grenzen %>% st_transform(4326)
  
  
  ## 0 Werte auf NA, damit transpartent in leaflet()
  r_dif@data@values[r_dif@data@values == 0] <<- NA
  
  ## +/-2m Werte auf NA, damit transpartent in leaflet()
  r_dif@data@values[(r_dif@data@values < 2) & (r_dif@data@values > -2)] <<- NA
  
}

3.4.1 Plot Hard

prep_leaflet_plots("Hard")
m <- leaflet(options = leafletOptions(minZoom = 13, maxZoom = 18)) %>%  
                   addProviderTiles(providers$CartoDB.Positron) %>% 
                   setView(8.514483, 47.382471, zoom = 15) %>% 
                   addRasterImage(r_dif, opacity = 0.5, colors = col_pal) %>%
                   addPolygons(data = df_buildings, color = "black", weight = 2,
                               fill = TRUE, fillOpacity = 0,
                               popup = ~str_c("Gebäudehöhe: ", h_rel_trau, " m <br>",
                                              "Status: ", sta)) %>% 
                   addPolygons(data = df_planned, color = "black", weight = 2,
                               dashArray = c(5, 5),
                               fill = TRUE, fillOpacity = 0,
                               popup = ~str_c("Gebäudehöhe: ", h_rel_trau, " m <br>",
                                              "Status: ", sta)) %>% 
                   addPolygons(data = df_borders, color = "black", weight = 3,
                               dashArray = c(5, 5),
                               fill = FALSE, fillOpacity = 0) %>% 
                   addMarkers(8.510041, 47.381294,
                               label = "Hardau Hochhäuser",
                               labelOptions = labelOptions(noHide = T)) %>%
                   addMarkers(8.519395, 47.381831,
                               label = "Polizei- und Justizzentrum (PJZ)",
                               labelOptions = labelOptions(noHide = T)) %>%
                   addLegend(colors = rev(colors_plot[-3]),
                             labels = (c("Mehr als 10m", "2 bis 10m",
                                         # "Weniger als 2m", 
                                         "2 bis 10m tiefer", "mehr als 10 Meter tiefer")),
                             title = "Erhöhung seit 2012",
                             position = "bottomright") # %>% 
m

3.4.2 Plot Escher Wyss

prep_leaflet_plots("Escher Wyss")
m <- leaflet(options = leafletOptions(minZoom = 13, maxZoom = 18)) %>%  
                   addProviderTiles(providers$CartoDB.Positron) %>% 
                                  # providers$CartoDB.Positron
                                  # providers$Stamen.Toner
                                  # providers$Jawg.Light
                   setView(8.514555, 47.382545, zoom = 15) %>% 
                   addRasterImage(r_dif, opacity = 0.5, colors = col_pal) %>%
                   addPolygons(data = df_buildings, color = "black", weight = 2,
                               fill = TRUE, fillOpacity = 0,
                               popup = ~str_c("Gebäudehöhe: ", h_rel_trau, " m <br>",
                                              "Status: ", sta)) %>% 
                   addPolygons(data = df_planned, color = "black", weight = 2,
                               dashArray = c(5, 5),
                               fill = TRUE, fillOpacity = 0,
                               popup = ~str_c("Gebäudehöhe: ", h_rel_trau, " m <br>",
                                              "Status: ", sta)) %>% 
                   addPolygons(data = df_borders, color = "black", weight = 3,
                               dashArray = c(5, 5),
                               fill = FALSE, fillOpacity = 0) %>% 
                   addMarkers(8.511765, 47.390203,
                               label = "Hochschule der Künste",
                               labelOptions = labelOptions(noHide = T)) %>%
                   addMarkers(8.517221, 47.386053,
                               label = "Prime Tower",
                               labelOptions = labelOptions(noHide = T)) %>%
                   addLegend(colors = rev(colors_plot[-3]),
                             labels = (c("Mehr als 10m", "2 bis 10m",
                                         # "Weniger als 2m", 
                                         "2 bis 10m tiefer", "mehr als 10 Meter tiefer")),
                             title = "Erhöhung seit 2012",
                             position = "bottomright") # %>% 
m

3.5 Statische PNG Plots

3.5.1 Beispiele: Saatlen

store_png_scale("Saatlen", "Saatlen", FALSE)

3.5.2 Beispiele: Wollishofen

store_png_scale("Wollishofen", "Wollishofen", FALSE)

3.5.3 Beispiele: Altstetten

store_png_scale("Altstetten", "Altstetten", FALSE)

3.5.4 Beispiele: Seebach

store_png_scale("Seebach", "Seebach", FALSE)

3.5.5 Beispiele: Alt Wiedikon

store_png_scale("Hirzenbach", "Hirzenbach", FALSE)

3.5.6 Beispiele: Langstrasse

store_png_scale("Langstrasse", "Langstrasse", FALSE)

3.5.7 Beispiele: Wollishofen

store_png_scale("Wollishofen", "Wollishofen", FALSE)

3.5.8 Beispiele: Escher Wyss

store_png_scale("Escher Wyss", "Escher Wyss", FALSE)

4 Analyse Hochhäuser

Wie viele Hochhäuser (höher als 25 m) gibt es?

Das kantonale Planungs- und Baugesetzt definiert ein Hochhaus ab einer Gebäudehöhe von 25 Metern.

Visualisierung Hochhäuser Stadt Zürich: https://hochhaeuser.stadt-zuerich.ch/

h_hochhaus <- 25

## Anzahl REAL existierender Hochhäuser, basierend auf TRAUFHÖHE

## Wie viele im 2012?
hoch_2012 <- shp_2_5_2012_all %>% filter(sta %in% c("erstellt", "real")) %>%
                                  filter(h_rel_trau > h_hochhaus)
hoch_quartiere_2012 <- hoch_2012 %>% st_drop_geometry() %>% group_by(Quartier) %>%
                                     summarise(Anzahl_2012 = n(),
                                               Area_2012 = sum(area),
                                               Volume_2012 = sum(volume_trauf),
                                                max_height_2012 = max(h_rel_trau))
## Wie viele im aktuell?
hoch_aktuell <- shp_2_5_aktuell_all %>% filter(sta %in% c("erstellt", "real")) %>%
                                        filter(h_rel_trau > h_hochhaus)
hoch_quartiere_aktuell <- hoch_aktuell %>% st_drop_geometry() %>% group_by(Quartier) %>%
                                           summarise(Anzahl_aktuell = n(),
                                                     Area_aktuell = sum(area),
                                                     Volume_aktuell = sum(volume_trauf),
                                                     max_height_aktuell = max(h_rel_trau))


## Wie viele sind aktuell geplant?
hoch_aktuell_geplant <- shp_2_5_aktuell_all %>% filter(sta %in% c("freigegeben", "eingereicht")) %>%
                                                filter(h_rel_trau > h_hochhaus)

hoch_quartiere_aktuell_geplant <- hoch_aktuell_geplant %>% st_drop_geometry() %>% group_by(Quartier) %>%
                                                           summarise(Anzahl_geplant = n(),
                                                                     Area_geplant = sum(area),
                                                                     Volume_geplant = sum(volume_trauf),
                                                                     max_height_geplant = max(h_rel_trau))

## Setze zusammen und berechne Veränderungen
hoch_quartiere <- hoch_quartiere_aktuell %>% left_join(hoch_quartiere_2012, by = "Quartier")
hoch_quartiere <- hoch_quartiere %>% mutate(Anzahl_increase = Anzahl_aktuell - Anzahl_2012 ,
                                            Area_increase = Area_aktuell - Area_2012,
                                            Volume_increase = Volume_aktuell - Volume_2012)

## Ergänze noch geplante Gebäude (eingereichte UND freigegebene Bauprojekte)
hoch_quartiere <- hoch_quartiere %>% left_join(hoch_quartiere_aktuell_geplant, by = "Quartier")

## Tabelle

hoch_quartiere_table <- hoch_quartiere %>% arrange(-Area_aktuell ) %>% 
                                           mutate_at(vars(-Quartier), funs(round(., 0))) 

# knitr::kable(hoch_quartiere_table, caption =  "", digits = 0) %>%
#   kable_styling(bootstrap_options = "striped", full_width = F, fixed_thead = T) %>%
#   scroll_box(width = "1080", height = "250px", fixed_thead = TRUE)


sketch = htmltools::withTags(table(
  class = 'display',
  thead(
    tr(
      th(rowspan = 1, ' '),
      th(colspan = 3, 'Stand heute'),
      th(colspan = 2, 'Zuwachs 2012-heute'),
      th(colspan = 3, 'Heute neu geplant')
    ),
    tr(
      lapply(c("Quartier",
               "Fläche [m2]", "Volumen [m3]", "max. Höhe [m]",
               "Fläche [m2]", "Volumen [m3]",
               "Fläche [m2]", "Volumen [m3]", "max. Höhe [m]"), th)
    )
  )
))
# 
# DT::datatable(hoch_quartiere_table,
#               caption = 'Hochhäuser in den Quartieren',
#               class = 'cell-border stripe')



DT::datatable(hoch_quartiere_table[, c("Quartier",
                                       "Area_aktuell", "Volume_aktuell", "max_height_aktuell",
                                       "Area_increase", "Volume_increase",
                                       "Area_geplant", "Volume_geplant", "max_height_geplant")],
              container = sketch, rownames = FALSE,
              caption = 'Volumen und Grundfläche der Hochhäuser',
              class = 'cell-border stripe')
## Plot für Check
# df_plot <- hoch_aktuell_geplant %>% filter(Quartier == "Alt-Wiedikon") %>% 
#                                      st_transform(4326)
# 
# df_plot_grenzen <- grenzen %>% filter(qname == "Alt-Wiedikon") %>% st_transform(4326)
# 
# m <- leaflet() %>% addTiles() %>% addPolygons(data = df_plot_grenzen, color = "black", fillOpacity = 0) %>% 
#                                   addPolygons(data = df_plot, popup = ~str_c("Höhe: ", h_rel_trau, "<br>",
#                                                                              "Status: ", sta, "<br>"))
# m